<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>ECMAScript 对象的作用域</title>
    <script>
       /*
       变量的作用域 是一个变量的适用范围
       这些作用域几乎毫无意义，因为 ECMAScript 中只存在一种作用域 - 公用作用域。
       ECMAScript 中的所有对象的所有属性和方法都是公用的。
       因此，定义自己的类和对象时，必须格外小心。记住，所有属性和方法默认都是公用的！
       */

        /*
        通常 由于缺少私有作用域，开发者确定了一个规约，说明哪些属性和方法应该被看做私有的。
        这种规约规定在属性前后加下划线：
        */
        function testPrivateProperty(){
            obj._color = "blue";  //  认为这是一个私有的属性
        }

        /*
        静态作用域
        静态作用域定义的属性和方法任何时候都能从同一位置访问。在 Java 中，类可具有属性和方法，
        无需实例化该类的对象，即可访问这些属性和方法，例如 java.net.URLEncoder 类，它的函数 encode() 就是静态方法。

        ECMAScript 没有静态作用域
        严格来说，ECMAScript 并没有静态作用域。不过，它可以给构造函数提供属性和方法。还记得吗，构造函数只是函数。
        函数是对象，对象可以有属性和方法。例如
        */
        function sayHello (){
            alert("hello")
        }

        sayHello.alternate = function (){
            alert('hi')
        }

        function testSayHello(){
            // 方法 alternate() 实际上是函数 sayHello 的方法。可以像调用常规函数一样调用 sayHello() 输出 "hello"，
            // 也可以调用 sayHello.alternate() 输出 "hi"。
            // 即使如此，alternate() 也是 sayHello() 公用作用域中的方法，而不是静态方法。
            sayHello();  // hello
            sayHello.alternate();  //  hi
            sayHello().alternate();  // hello
        }

        /*
        关键字 this
        关键字 this 总是指向调用该方法的对象
        */
        function simpleThisTest(){
            var oCar = new Object;
            oCar.color = "red";
            oCar.showColor = function() {
                alert(this.color);
            };
            oCar.sShowColor = function(){
                alert(oCar.color);   // 这里的this 和 oCar 其实是一样的
            }

            oCar.showColor()

        }

        /*
        用 this 的原因
        为什么使用 this 呢？因为在实例化对象时，总是不能确定开发者会使用什么样的变量名
        。使用 this，即可在任何多个地方重用同一个函数。请思考下面的例子：
        */
        function showColor(){
            alert(this.color)
        }

        function testThisColor(){
            //
            var oCar1 = new Object;
            oCar1.color = "red";
            oCar1.showColor = showColor;

            var oCar2 = new Object;
            oCar2.color = "blue";
            oCar2.showColor = showColor;

            oCar1.showColor();		//输出 "red"
            oCar2.showColor();		//输出 "blue"
        }


    </script>
</head>
<body>
    <button onclick="testSayHello()">测试 say Hello </button>
    <button onclick="simpleThisTest()">测试 this </button>
    <button onclick="testThisColor()">测试 多个  this color</button>
</body>
</html>